﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using Csla.Core;
using System.ComponentModel;

namespace OpenExpressApp.Editors
{
    /// <summary>
    /// 属性编辑器
    /// 
    /// 所有的属性编辑器的基类
    /// </summary>
    public abstract class PropertyEditor : IPropertyEditor
    {
        private object _control;

        private object _readOnlyControl;

        private object _labelControl;

        private BusinessObjectPropertyInfo _propertyInfo;

        private IList<IReadOnlyChecker> _isReadOnlyChecker;

        private IList<IVisibleChecker> _isVisibleChecker;

        /// <summary>
        /// 创建控件对象
        /// </summary>
        /// <param name="propertyInfo">被编辑的属性</param>
        /// <param name="view">被编辑的视图</param>
        public PropertyEditor(IObjectView view)
        {
            if (view == null) throw new ArgumentNullException("view");

            this.View = view;
        }

        /// <summary>
        /// 所处的视图
        /// </summary>
        public IObjectView View { get; private set; }

        /// <summary>
        /// 被编辑的属性
        /// </summary>
        public BusinessObjectPropertyInfo PropertyInfo
        {
            get
            {
                Debug.Assert(this._propertyInfo != null, "在使用Editor之前必须给PropertyInfo赋值");
                return this._propertyInfo;
            }
            set
            {
                this._propertyInfo = value;
            }
        }

        /// <summary>
        /// 被编辑的属性的当前值
        /// "View.CurrentObject.(PropertyInfo.Name)"
        /// </summary>
        public object PropertyValue
        {
            get
            {
                //Debug.Assert(View.ControlCreated, "PropertyValue必须在ControlCreated后使用");
                return (View.CurrentObject as BusinessBase).GetPropertyValue(_propertyInfo.Name);
            }
            set
            {
                var currentObject = this.View.CurrentObject as BusinessBase;
                //已经选中了，再设置值。
                if (currentObject != null)
                {
                    //if ((PropertyValue != value) && (null != PropertyChanged))
                    //    PropertyChanged(this, new PropertyChangedEventArgs(_propertyInfo.Name));
                    currentObject.SetPropertyValue(this._propertyInfo.Name, value);
                    this.OnPropertyValueChanged();
                }
            }
        }

        /// <summary>
        /// 当前使用的control
        /// </summary>
        public object Control
        {
            get
            {
                if (this._control == null) throw new InvalidOperationException("请先调用EnsureControlsCreated方法！");
                return _control;
            }
        }

        /// <summary>
        /// 当前的LabelControl
        /// </summary>
        public object LabelControl
        {
            get
            {
                if (this._labelControl == null) throw new InvalidOperationException("请先调用EnsureControlsCreated方法！");
                return _labelControl;
            }
        }

        /// <summary>
        /// 当前的ReadOnlyControl
        /// </summary>
        public object ReadOnlyControl
        {
            get
            {
                if (this._readOnlyControl == null) throw new InvalidOperationException("请先调用EnsureControlsCreated方法！");
                return _readOnlyControl;
            }
        }

        /// <summary>
        /// 属性编辑器是否可见
        /// </summary>
        public bool IsVisible
        {
            get
            {
                if (this._isVisibleChecker != null)
                {
                    foreach (var checker in this._isVisibleChecker)
                    {
                        if (checker.IsVisible(this) == false)
                        {
                            return false;
                        }
                    }
                }

                if (null != PropertyInfo.IsVisibleAttribute)
                {
                    string visibleProp = PropertyInfo.IsVisibleAttribute.PropertyName;
                    if (string.IsNullOrEmpty(visibleProp))
                    {
                        return true;
                    }
                    if (null != View.CurrentObject)
                    {
                        return (Boolean)View.CurrentObject.GetPropertyValue(visibleProp);
                    }
                }
                return true;
            }
        }

        /// <summary>
        /// 这个属性是否是只读的
        /// </summary>
        public bool IsReadOnly
        {
            get
            {
                //类指明为只读
                if (this._propertyInfo.RuntimeProperty.CanWrite == false ||
                    this._propertyInfo.BoInfo.NotAllowEdit
                    )
                {
                    return true;
                }

                if (this._isReadOnlyChecker != null)
                {
                    foreach (var checker in this._isReadOnlyChecker)
                    {
                        if (checker.IsReadOnly(this))
                        {
                            return true;
                        }
                    }
                }

                //使用IsReadOnlyAttribute属性指明另一个属性来查询是否只读
                if (null != this._propertyInfo.IsReadOnlyAttribute)
                {
                    string readonlyProp = this._propertyInfo.IsReadOnlyAttribute.PropertyName;
                    if (string.IsNullOrEmpty(readonlyProp))
                    {
                        return true;
                    }
                    if (null != View.CurrentObject)
                    {
                        return (Boolean)View.CurrentObject.GetPropertyValue(readonlyProp);
                    }
                }
                return false;
            }
        }

        public event EventHandler PropertyValueChanged;

        /// <summary>
        /// 确保已经生成所有需要使用的控件
        /// </summary>
        /// <returns></returns>
        public void EnsureControlsCreated()
        {
            if (this._control == null || this._labelControl == null || this._readOnlyControl == null)
            {
                var view = this.View;
                if (view == null || this._propertyInfo == null) throw new InvalidOperationException("view != null && this._propertyInfo != null");

                view.AddPropertyEditor(this);

                //放在CreateControlCore后,因为CreateLabelControl可能会用刚才生成的Control
                this._control = this.EditingControlGenerator.CreateControl();
                this._labelControl = this.LabelControlGenerator.CreateControl();
                this._readOnlyControl = this.ReadOnlyControlGenerator.CreateControl();

                this.OnControlsCreated();
            }
        }

        public void RegisterChecker(IReadOnlyChecker checker)
        {
            //if (checker == null) throw new ArgumentNullException("checker");

            if (this._isReadOnlyChecker == null)
            {
                this._isReadOnlyChecker = new List<IReadOnlyChecker>();
            }

            if (this._isReadOnlyChecker.Contains(checker) == false)
            {
                this._isReadOnlyChecker.Add(checker);
            }
        }

        public void RegisterChecker(IVisibleChecker checker)
        {
            if (checker == null) throw new ArgumentNullException("checker");

            if (this._isVisibleChecker == null)
            {
                this._isVisibleChecker = new List<IVisibleChecker>();
            }

            if (this._isVisibleChecker.Contains(checker) == false)
            {
                this._isVisibleChecker.Add(checker);
            }
        }

        /// <summary>
        /// 创建一个新的control
        /// </summary>
        /// <returns></returns>
        protected abstract object CreateEditingControlCore();

        /// <summary>
        /// 控件创建完成后的事件
        /// </summary>
        protected virtual void OnControlsCreated() { }

        protected virtual void OnPropertyValueChanged()
        {
            if (this.PropertyValueChanged != null)
            {
                this.PropertyValueChanged(this, EventArgs.Empty);
            }
        }

        #region IPropertyEditor Members

        public abstract IControlGenerator EditingControlGenerator { get; }

        public abstract IControlGenerator ReadOnlyControlGenerator { get; }

        public abstract IControlGenerator LabelControlGenerator { get; }

        //object IControlGenerator.CreateControl()
        //{
        //    return this.CreateEditingControlCore();
        //}
        IEntityPropertyInfo ISimplePropertyEditor.PropertyInfo
        {
            get
            {
                return this.PropertyInfo;
            }
            set
            {
                this.PropertyInfo = value as BusinessObjectPropertyInfo;
            }
        }

        #endregion
    }
}
